#coding=utf-8
#
# Copyright (C) 2014  NianNian TECH Co., Ltd. All rights reserved.
# Created on May 9, 2014, by Junn
#
from core.models import BaseModel
from django.db import models
from users.models import User, PDU_ITEMS
from managers import FamilyManager
from utils import logs
from django.dispatch.dispatcher import receiver
from posts.signals import s_post_added
from django.db.models import F
from django.core.cache import cache
import settings


FAMILY_STATUS_CHOICES = (
    ('O', u'正常使用'),
    ('D', u'已删除'),
)

VALID_FAMILY_ATTRS = ('name', 'about')

def mk_key(id):
    return 'f%s' % id

class NoneFamily(object):
    
    def __init__(self):
        pass
    
    def get_member(self, uid):
        return None  
    
    def remove_member(self, user):
        return False

class Family(BaseModel):
    '''家庭'''
    
    creator = models.ForeignKey(User, verbose_name=u'创建者')
    name    = models.CharField(max_length=50, verbose_name=u'名称',  default=u'未命名')
    about   = models.CharField(max_length=100, verbose_name=u'介绍', null=True, blank=True, default='') #签名或介绍
    members = models.ManyToManyField(User, through='FamilyShip', verbose_name=u'家庭成员',
                                     related_name='members')
    status = models.CharField(u'状态', max_length=1, choices=FAMILY_STATUS_CHOICES, default='O')

    objects = FamilyManager()
    none_family = NoneFamily()
    
    class Meta:
        verbose_name = u'家庭'
        verbose_name_plural = u'家庭'
        
    def __init__(self, *args, **kwargs):
        self._cached_members = {}
        super(Family, self).__init__(*args, **kwargs)
            
    def __unicode__(self):
        return u'%s, %s' % (self.id, self.name)
    
    def is_deleted(self):
        return True if self.status == 'D' else False
    
    def has_other_members(self):  
        '''家庭内是否有除创建者的其他成员'''
        return True if FamilyShip.objects.filter(family=self).exclude(member=self.creator) else False
    
    def update(self, data):
        for attr in VALID_FAMILY_ATTRS:  #双重循环, 以后需要改进算法
            if attr in data:
                setattr(self, attr, data.get(attr))

        self.save()
        self.cache()
        
    def cache(self): #TODO
        '''将family实体对象进行缓存, 以 f+id作为key '''
        cache.set(mk_key(self.id), self, timeout=0)   #永不过期
        
    def cache_all_members(self):
        '''缓存所有家庭成员信息'''
        fships = FamilyShip.objects.filter(family=self)
        for fs in fships:
            self._cached_members['%s' % fs.member_id] = FamilyMember(User.objects.get_cached(fs.member_id), self, fship=fs)
        
    def clear_cache(self):
        cache.delete(mk_key(self.id))
        
    def make_delete(self):
        # clear the family for all members
        for mid in self._cached_members:
            user = self._cached_members[mid].get_user
            if user._is_family_cached():
                user.clear_cached_family()
        
        FamilyShip.objects.filter(family=self).delete()
        self.clear_cache()
        self.status = 'D'
        self.save()    
        logs.debug('family deleted: %s' % self.id)
        
    def get_member(self, uid):
        '''根据uid获取FamilyMember对象'''
        if hasattr(self, '_cached_members') and self._cached_members:
            member = self._cached_members.get('%s' % uid)
            if member: 
                return member 
        
        try:
            fs = FamilyShip.objects.filter(family=self, member_id=int(uid))
            if not fs: return None
            member = FamilyMember(User.objects.get_cached(uid), self, fship=fs[0])
            #self._cached_members['%s' % uid] = member   #why we can't add this line ???
            return member
        except Exception:
            logs.debug('Member %s not found in family %s' % (uid, self.id))
            return None  
                
    def all_members(self):
        '''返回所有家庭成员, 并进行缓存'''
        if hasattr(self, '_cached_members') and self._cached_members:
            return self._cached_members
        
        self.cache_all_members()
        return self._cached_members
    
    def is_members_full(self):
        '''成员数是否已达最大值'''
        return True if len(self.all_members()) >= settings.MAX_MEMBERS_COUNT else False
        
    def add_member(self, user): #TODO
        fs = FamilyShip(family=self, member=user)
        fs.save() 
        
        if not hasattr(self, '_cached_members'):
            logs.info('add_member.hasattr()================>')
            self._cached_members = {}
        member = FamilyMember(user, self, fship=fs)    
        self._cached_members['%s' % user.id] = member   
        logs.info('Member %s added into family %s by user %s ' % (user.id, self.id, self.creator.id))
        return member
    
    def remove_member(self, user):
        try:
            if self._cached_members: self._cached_members.pop(user.id)
            fs = FamilyShip.objects.get(family=self,member=user)
            fs.delete()
            
            user.clear_cached_family()
            logs.info('member %s removed from family %s by user %s ' % (user.id, self.id, self.creator.id))
            return 1
        except Exception, e:
            logs.error('Remove member exception: %s' % e)
            return 0 
            
    def build_member(self, user):
        return FamilyMember(user, self) 
    
    def get_all_posts(self):
        return self.post_set.all().order_by('-created_time')
    
    def get_paged_posts(self, last_time, count=10):
        '''传入上次请求数据页最后一条记录的创建时间和请求数据条数, 返回分页后的数据'''
        if not last_time:
            return self.post_set.all().order_by('-created_time')[:count]
        return self.post_set.filter(created_time__lt=last_time).order_by('-created_time')[:count]
    
    def incr_posts_unread_count(self, user): #TODO: using cache later...
        '''除传入的user外, 家庭内其他成员的新动态未读计数+1'''
        FamilyShip.objects.filter(family=self).exclude(member=user).update(unread_count=F('unread_count') + 1)
        
    def get_posts_unread_count(self, user):  #Family model method
        try:
            return FamilyShip.objects.get(family=self, member=user).unread_count
        except Exception, e:
            logs.error('User % s get_posts_unread_count in family %s error: \n %s' % (user.id, self.id, e))
            return 0

    def clear_unread_count(self, user):
        '''将指定用户未读动态计数清0'''
        upc = FamilyShip.objects.get(family=self, member=user)
        upc.unread_count = 0
        upc.save()        
        

class FamilyShip(BaseModel):
    '''家庭与成员关系, 多对多'''
    
    family = models.ForeignKey(Family)
    member = models.ForeignKey(User)
    innername = models.CharField(max_length=20, default='', verbose_name=u'称呼')  #成员在家庭内部的称呼
    unread_count = models.IntegerField(default=0)       #未读新动态条数
     
    class Meta:
        verbose_name = u'家庭与成员关系'
        verbose_name_plural = u'家庭与成员关系'   
                
    def __unicode__(self):
        return u'member:%s, family:%s' % (self.member_id, self.family_id)
                
VALID_MEMBER_ATTRS = ('innername',)
        
class NoneMember(object):
    def __init__(self):
        pass
            
    def __unicode__(self):
        return 'NoneMember'        
        
class FamilyMember(object):
    '''家庭成员类, 用于对操作家庭某特定成员'''
    
    def __init__(self, user, family, fship=None):
        self._user = user
        self._family = family
        self._fship = fship
        
    def __unicode__(self):
        return u'%s, %s' % (self._user, self._family)
        
    @property    
    def id(self):
        return self._user.id
    
    @property
    def get_user(self):
        return self._user
    
    def get_familyship(self):
        ships = FamilyShip.objects.filter(family=self._family, member=self._user) #TODO: change this, don't get from db... 
        return ships[0]
    
    @property
    def get_innername(self):
        try:
            return self.get_familyship().innername
        except Exception, e:
            logs.error('%s' % e)
            return ''
        #return self._fship.innername if self._fship else '' 
    
    #前期一个用户仅在一个家庭. 若用户可加入多个家庭, 则需修改构造函数
    @property
    def get_family(self): 
        return self._family
    
    def is_admin(self): #是否家庭管理员, 以后有多种权限可修改该方法
        return self.is_creator()
    
    def is_creator(self): #是否家庭创建者
        try:
            return True if self._user == self._family.creator else False
        except Exception, e: 
            logs.info('%s' % e)
            return False
    
    def update(self, data, files=None):
        avatar = None
        if files:
            avatar = files.get('avatar')
        self._user.update(data, new_avatar=avatar)
        
        if 'innername' in data:
            fs = self.get_familyship()
            setattr(fs, 'innername', data.get('innername'))
            self._user.updatePdu(PDU_ITEMS.get('innername'))
            self._user.save()
            fs.save()
            
# class PostUnreadCount(BaseModel):
#     '''未读动态数据计数'''
#     user = models.ForeignKey(User, verbose_name=u'用户', unique=True)
#     family = models.ForeignKey(Family, verbose_name=u'家庭')
#     unread_count = models.IntegerField(default=0)
#     updated_time = models.DateTimeField(u'更新时间', auto_now=True)
#         
#     class Meta:
#         verbose_name = u'未读动态计数'
#         verbose_name_plural = u'未读动态计数'
#         
#     def __unicode__(self):
#         return u'%s, %s' % (self.id, self.unread_count)


@receiver(s_post_added)
def update_posts_unread_count(sender, **kwargs):
    user = kwargs.pop('user', None)
    family = kwargs.pop('family', None)
    if not family or not user:
        return
    family.incr_posts_unread_count(user)            
    logs.info('update_posts_unread_count done for family %s' % family.id)        
    
    
